//
//  CacheService.swift
//  
//
//  Created by tank on 2021/11/17.
//

import Foundation
import UIKit
import WebKit
import Logging
import RxSwift
import LibBase

class CacheService: CacheServiceProtocol {
    var logger = Logger(label: "LibService.CacheService")
    
    private var disposeBag: DisposeBag!
    
    weak var delegate: CacheServiceDelegate?
    
    let globalCache: CacheProtocol = LevelDBCache(path: nil)
    
    let globalRemovableCache: CacheProtocol = LevelDBCache(path: "R")
    
    var userCache: CacheProtocol?
    
    var userRemovableCache: CacheProtocol?
    
    init() {
        logger.logLevel = .debug
    }
    
    func setUserCache() {
        disposeBag = DisposeBag()
        
        guard let authService = ServiceManager.shared.authService else {
            userCache = nil
            userRemovableCache = nil
            return
        }
        
        authService.authRepository
            .dataObservable
            .subscribe(onNext: { [weak self] authModel in
                guard let strongSelf = self else {
                    return
                }
                
                guard let authModel = authModel else {
                    strongSelf.clearUserCache()
                    return
                }
            
                strongSelf.initUserCache(userId: authModel.userId)
            })
            .disposed(by: disposeBag)
        
        if let authModel = authService.authRepository.data {
            initUserCache(userId: authModel.userId)
        } else {
            clearUserCache()
        }
    }
    
    private func initUserCache(userId: String) {
        userCache = LevelDBCache(path: userId)
        userRemovableCache = LevelDBCache(path: "R" + userId)
    }
    
    private func clearUserCache() {
        userCache = nil
        userRemovableCache = nil
    }
    
    func getCacheSize() -> CGFloat {
        let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory,
                                                        .userDomainMask,
                                                        true)
        guard paths.count > 0 else {
            return 0
        }

        var totalSize: CGFloat = 0
        let path = paths[0]
        let fileManager = FileManager.default
        if fileManager.fileExists(atPath: path),
            let childrenFile = fileManager.subpaths(atPath: path) {
            
            for file in childrenFile {
                let absoluteURL = URL(fileURLWithPath: path).appendingPathComponent(file)
                do {
                    if let size = try fileManager.attributesOfItem(atPath: absoluteURL.path)[FileAttributeKey.size] as? CGFloat {
                        totalSize += size
                    }
                } catch {
                    logger.error(Logger.Message(stringLiteral: error.localizedDescription))
                }
            }
        }

        return totalSize / 1024.0 / 1024.0
    }
    
    func clearCache(completion: ClearCacheCompletion?){
        let cacheSize = getCacheSize()
        logger.info("cacheSize = \(cacheSize)")
        
        // WebView Cache
        let set = WKWebsiteDataStore.allWebsiteDataTypes()
        let date = Date(timeIntervalSince1970: 0)
        WKWebsiteDataStore.default()
            .removeData(ofTypes: set,
                        modifiedSince: date) { [weak self] in
                self?.logger.info("Remove web view cache completion！")
            }
        
        do {
            try FileManager.default.removeItem(at: FileManager.ex.downloadDirectory)
        } catch {
            logger.error(Logger.Message(stringLiteral: error.localizedDescription))
        }
        
        globalRemovableCache.removeAll()
        userRemovableCache?.removeAll()
        
        guard let delegate = delegate else {
            completion?(true)
            return
        }
        
        delegate.clearCache(completion: completion)
    }
}
